home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume15 / dmake-3.6 / part19 < prev    next >
Encoding:
Text File  |  1990-10-14  |  39.3 KB  |  1,302 lines

  1. Newsgroups: comp.sources.misc
  2. X-UNIX-From: dvadura@watdragon.waterloo.edu
  3. subject: v15i071: dmake version 3.6 (part 19/25)
  4. from: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 15, Issue 71
  8. Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  9. Archive-name: dmake-3.6/part19
  10.  
  11. #!/bin/sh
  12. # this is part 19 of a multipart archive
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file make.c continued
  15. #
  16. CurArch=19
  17. if test ! -r s2_seq_.tmp
  18. then echo "Please unpack part 1 first!"
  19.      exit 1; fi
  20. ( read Scheck
  21.   if test "$Scheck" != $CurArch
  22.   then echo "Please unpack part $Scheck next!"
  23.        exit 1;
  24.   else exit 0; fi
  25. ) < s2_seq_.tmp || exit 1
  26. echo "x - Continuing file make.c"
  27. sed 's/^X//' << 'SHAR_EOF' >> make.c
  28. X   Explode_prq( Fringe_hd, NIL(CELL), FALSE );
  29. X
  30. X   _set_recipe( ".GROUPPROLOG", RP_GPPROLOG );
  31. X   _set_recipe( ".GROUPEPILOG", RP_GPEPILOG );
  32. X
  33. X   while( !done ) {
  34. X      done = F_MADE;
  35. X      for( lp = Fringe_hd; lp != NIL(LINK); lp = lp->cl_next ) {
  36. X     int rval = 0;
  37. X
  38. X     Root = lp->cl_prq;
  39. X     if( (rval |= Make(Root, Root->CE_HOW, NIL(CELL))) == -1 )
  40. X        DB_RETURN(1);
  41. X     else
  42. X        done &= (Root->ce_flag & F_MADE);
  43. X
  44. X     if( !rval && !done ) Wait_for_child( FALSE, -1 );
  45. X      }
  46. X   }
  47. X
  48. X   for( lp = Fringe_hd; lp != NIL(LINK); lp = lp->cl_next ) {
  49. X      Root = lp->cl_prq;
  50. X      if( !(Root->ce_attr & A_UPDATED) )
  51. X     printf( "`%s' is up to date\n", Root->CE_NAME );
  52. X   }
  53. X
  54. X   DB_RETURN( 0 );
  55. X}
  56. X
  57. X
  58. X
  59. Xint
  60. XMake( cp, how, setdirroot )/*
  61. X=============================  Make a specified target */
  62. XCELLPTR cp;
  63. XHOWPTR  how;
  64. XCELLPTR setdirroot;
  65. X{
  66. X   register LINKPTR dp;
  67. X   register CELLPTR tcp;
  68. X   char            *name, *lib;
  69. X   HASHPTR        m_at    = NIL(HASH);
  70. X   char             *all    = NIL(char);
  71. X   char             *inf    = NIL(char);
  72. X   char             *outall = NIL(char);
  73. X   char             *imm    = NIL(char);
  74. X   int              rval    = 0;
  75. X   int            push    = 0;
  76. X   time_t           otime   = (time_t) 1L;
  77. X   time_t        ttime   = (time_t) 1L;
  78. X
  79. X   DB_ENTER( "Make" );
  80. X   DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
  81. X
  82. X   /* NOTE:  The only time we are called with a NIL how pointer is for
  83. X    *         cells that are to be statted only or for cells that are destined
  84. X    *         to have a set of rules inferred for them. */
  85. X
  86. X   if( how == NIL(HOW) ) {
  87. X      TALLOC( cp->CE_HOW, 1, HOW );
  88. X      how = cp->CE_HOW;
  89. X   }
  90. X
  91. X   /* Check to see if we have made the node already.  If so then don't do
  92. X    * it again, except if the cell's ce_setdir field is set to something other
  93. X    * than the value of setdirroot.  If they differ then, and we have made it
  94. X    * already, then make it again and set the cell's stat bit to off so that
  95. X    * we do it again. */
  96. X
  97. X   if( how->hw_flag & F_VISITED ) {
  98. X      /* we may return if we made it already from the same setdir location,
  99. X       * or if it is not a library member whose lib field is non NULL.  (if
  100. X       * it is such a member then we have a line of the form:
  101. X       *    lib1 lib2 .LIBRARY : member_list...
  102. X       * and we have to make sure all members are up to date in both libs. */
  103. X
  104. X      if( cp->ce_setdir == setdirroot &&
  105. X      !((cp->ce_attr & A_LIBRARYM) && (cp->ce_lib != NIL(char))) )
  106. X     DB_RETURN( 0 );
  107. X
  108. X      /* We check to make sure that we are comming from a truly different
  109. X       * directory, ie. ".SETDIR=joe : a.c b.c d.c" are all assumed to come
  110. X       * from the same directory, even though setdirroot is different when
  111. X       * making dependents of each of these targets. */
  112. X
  113. X      if( cp->ce_setdir != NIL(CELL) && setdirroot != NIL(CELL) &&
  114. X          cp->ce_setdir->ce_dir == setdirroot->ce_dir )
  115. X         DB_RETURN( 0 );
  116. X
  117. X      cp->ce_flag  &= ~(F_STAT|F_VISITED|F_MADE);
  118. X      how->hw_flag &= ~(F_VISITED|F_MADE);
  119. X   }
  120. X
  121. X   if( how->hw_next != NIL(HOW))
  122. X      if( (rval = Make(cp, how->hw_next, setdirroot)) == -1 ||
  123. X      !(how->hw_next->hw_flag & F_MADE) )
  124. X     goto stop_making_it;
  125. X
  126. X   /* If we are supposed to change directories for this target then do so.
  127. X    * If we do change dir, then modify the setdirroot variable to reflect
  128. X    * that fact for all of the prerequisites that we will be making. */
  129. X
  130. X   cp->ce_setdir = setdirroot;
  131. X
  132. X   if( cp->ce_attr & A_SETDIR ) {
  133. X      /* Change directory only if the previous .SETDIR is a different
  134. X      /* directory from the current one.  ie. all cells with the same .SETDIR
  135. X      /* attribute are assumed to come from the same directory. */
  136. X
  137. X      if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != cp->ce_dir) &&
  138. X          (push = Push_dir(cp, (((cp->ce_attr|Glob_attr)&A_IGNORE) != 0))) )
  139. X     setdirroot = cp;
  140. X   }
  141. X
  142. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  143. X   if( (how->hw_recipe == NIL(STRING) && !(how->hw_flag & F_INFER)) ) {
  144. X      HOWPTR thp;
  145. X      
  146. X      if( Verbose )
  147. X     printf( "%s:  Infering prerequisite(s) and recipe for [%s]\n", Pname,
  148. X          cp->CE_NAME );
  149. X
  150. X      thp = how->hw_next;
  151. X      (void) Infer_recipe( cp, how, NIL(DFASET), setdirroot );
  152. X
  153. X      /* If we inferred a new set of prerequisites then make
  154. X       * them before the current list represented by the current how pointer */
  155. X      if( thp != how->hw_next )
  156. X     if( (rval = Make(cp, how->hw_next, cp->ce_setdir)) == -1 ||
  157. X         !(how->hw_next->hw_flag & F_MADE) )
  158. X        goto stop_making_it;
  159. X   }
  160. X
  161. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  162. X   /* If we have not yet statted the target then do so. */
  163. X   if( !(cp->ce_flag & F_STAT) ) {
  164. X      time_t itime = cp->ce_time;
  165. X      Stat_target( cp, TRUE );
  166. X
  167. X      if( cp->ce_time == (time_t)0L ) {
  168. X         if( cp->ce_flag & F_INFER )
  169. X        cp->ce_time = itime;
  170. X      }
  171. X      else
  172. X         cp->ce_attr |= A_PRECIOUS;  /* File exists so don't remove it later. */
  173. X
  174. X      if( Verbose )
  175. X     printf("%s:  Time stamp of [%s] is %ld\n",Pname,cp->CE_NAME,
  176. X            cp->ce_time);
  177. X   }
  178. X
  179. X   DB_PRINT( "make", ("(%s, %ld, 0x%08x, 0x%04x)", cp->CE_NAME,
  180. X            cp->ce_time, cp->ce_attr, cp->ce_flag) );
  181. X
  182. X   if( !(cp->ce_flag & F_TARGET) && (cp->ce_time == (time_t) 0L) )
  183. X      if( Makemkf )
  184. X     DB_RETURN( -1 );
  185. X      else
  186. X     Fatal( "`%s' not found, and can't be made", cp->CE_NAME );
  187. X
  188. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  189. X
  190. X   /* set value of $* if we have not infered a recipe, in this case $* is
  191. X    * the same as $(@:db), this allows us to be compatible with BSD make */
  192. X   if( how->hw_per == NIL(char) ) how->hw_per = "$(@:db)";
  193. X
  194. X   for( dp = how->hw_prq; dp != NIL(LINK); dp = dp->cl_next ) {
  195. X      int seq;
  196. X
  197. X      /* Make the prerequisite, note that if the current target has the
  198. X       * .LIBRARY attribute set we pass on to the prerequisite the .LIBRARYM
  199. X       * attribute and pass on the name of the current target as the library
  200. X       * name, and we take it away when we are done.  */
  201. X
  202. X      tcp = dp->cl_prq;
  203. X      seq = (((cp->ce_attr | how->hw_attr | Glob_attr) & A_SEQ) != 0);
  204. X
  205. X      if( tcp->ce_flag & F_VISITED )
  206. X     if( tcp->ce_flag & F_MADE ) {
  207. X        if( tcp->ce_time > ttime ) ttime = tcp->ce_time;
  208. X        continue;
  209. X     }
  210. X     else
  211. X        goto stop_making_it;
  212. X
  213. X      if( strchr(tcp->CE_NAME, '$') ) {
  214. X     /* Make this prerequisite link point at the real prerequisite we
  215. X      * are after, ie figure out what the dynamic one is and point at it. */
  216. X
  217. X     m_at = Def_macro( "@", cp->ce_fname, M_MULTI );
  218. X     name = Expand( tcp->CE_NAME );
  219. X
  220. X     tcp = dp->cl_prq = Def_cell( name, setdirroot );
  221. X     FREE( name );
  222. X      }
  223. X
  224. X      if( cp->ce_attr & A_LIBRARY ) {
  225. X         tcp->ce_attr |= A_LIBRARYM;
  226. X     tcp->ce_lib   = cp->ce_fname;
  227. X      }
  228. X
  229. X      if( (tcp->ce_flag & (F_INFER|F_STAT))==F_INFER && cp->ce_time > ttime )
  230. X     tcp->ce_time = cp->ce_time;
  231. X
  232. X      /* Propagate parents F_REMOVE and F_INFER attribute to children.
  233. X       * Make certain you do this AFTER propagating the time, since the
  234. X       * time propagation test above uses the F_INFER flag to decide if
  235. X       * it should do so. */
  236. X      tcp->ce_flag |= cp->ce_flag & (F_REMOVE|F_INFER);
  237. X
  238. X      rval |= Make(tcp, tcp->CE_HOW, setdirroot);
  239. X
  240. X      if( cp->ce_attr & A_LIBRARY )
  241. X         tcp->ce_attr ^= A_LIBRARYM;
  242. X
  243. X      if( rval == -1 || (seq && (rval == 1)) )
  244. X     goto stop_making_it;
  245. X
  246. X      if( tcp->ce_time > ttime ) ttime = tcp->ce_time;
  247. X   }
  248. X
  249. X   /* Do the loop again.  We are most definitely going to make the current
  250. X    * how cell now.  NOTE:  doing this loop here also results in a reduction
  251. X    * in peak memory usage by the algorithm. */
  252. X
  253. X   for( dp = how->hw_prq; dp != NIL(LINK); dp = dp->cl_next ) {
  254. X      char *dir;
  255. X      int  tgflg;
  256. X      tcp  = dp->cl_prq;
  257. X      name = tcp->ce_fname;
  258. X
  259. X      /* make certain that all prerequisites are made prior to advancing. */
  260. X      if( !(tcp->ce_flag & F_MADE) ) goto stop_making_it;
  261. X
  262. X      /* If the target is a library, then check to make certain that a member
  263. X       * is newer than an object file sitting on disk.  If the disk version
  264. X       * is newer then set the time stamps so that the archived member is
  265. X       * replaced. */
  266. X      if( cp->ce_attr & A_LIBRARY )
  267. X     if( tcp->ce_time < cp->ce_time ) {
  268. X        time_t mtime = Do_stat( tcp->ce_fname, tcp->ce_lib, NIL(char *) );
  269. X        if( mtime < tcp->ce_time ) tcp->ce_time = cp->ce_time+1L;
  270. X     }
  271. X
  272. X      if( tcp->ce_time > otime ) otime = tcp->ce_time;
  273. X
  274. X      /* Note:  If the prerequisite was made using a SETDIR
  275. X       *     directory then we will include the directory in the name
  276. X       *    of the prerequisite when we build the $?, $&, $^ and $< lists
  277. X       */
  278. X
  279. X      if( (dir = tcp->ce_dir ) != NIL(char) )
  280. X     name = Build_path( dir, name );
  281. X
  282. X      all  = _strapp( all, name );
  283. X      if( tgflg = (dp->cl_flag & F_TARGET) ) inf = _strapp( inf, name );
  284. X
  285. X      if((cp->ce_time<tcp->ce_time) || ((tcp->ce_flag & F_TARGET) && Force)) {
  286. X         outall = _strapp( outall, name );
  287. X         if( tgflg ) imm = _strapp( imm, name );
  288. X      }
  289. X   }
  290. X
  291. X   DB_PRINT( "mem", ("%s:-C mem %ld", cp->CE_NAME, (long) coreleft()) );
  292. X   DB_PRINT( "make", ("I make '%s' if %ld > %ld", cp->CE_NAME, otime,
  293. X          cp->ce_time) );
  294. X
  295. X   /* mark the how cell as visited since we are making it for certain now. */
  296. X   how->hw_flag |= F_VISITED;
  297. X   if( Verbose ) printf( "%s:  >>>> Making [%s]\n", Pname, cp->CE_NAME );
  298. X
  299. X   if( Check && (cp->ce_time < otime) ) {
  300. X      /* Only checking so stop as soon as we determine we will make something */
  301. X      rval = -1;
  302. X      goto stop_making_it;
  303. X   }
  304. X
  305. X   if( (cp->ce_time < otime) || ((cp->ce_flag & F_TARGET) && Force) ) {
  306. X      if( Verbose )
  307. X     printf( "%s:  Updating [%s], (%ld > %ld)\n", Pname,
  308. X         cp->CE_NAME, otime, cp->ce_time );
  309. X
  310. X      cp->ce_attr |= A_UPDATED;
  311. X
  312. X      if( Touch ) {
  313. X     name = cp->ce_fname;
  314. X     lib  = cp->ce_lib;
  315. X
  316. X     if( !(Glob_attr & A_SILENT) || !Trace )
  317. X        if( lib == NIL(char) )
  318. X           printf("touch(%s)", name );
  319. X        else if( cp->ce_attr & A_SYMBOL )
  320. X           printf("touch(%s((%s)))", lib, name );
  321. X        else
  322. X           printf("touch(%s(%s))", lib, name );
  323. X
  324. X     if( !Trace )
  325. X        if( Do_touch( name, lib,
  326. X        (cp->ce_attr & A_SYMBOL) ? &name : NIL(char *) ) != 0 )
  327. X           printf( "  not touched - non-existant" );
  328. X
  329. X     printf( "\n" );
  330. X     Update_time_stamp( cp, how );
  331. X      }
  332. X      else if( how->hw_recipe != NIL(STRING) ) {
  333. X     HASHPTR m_q, m_b, m_g, m_l, m_bb, m_up;
  334. X     TKSTR   tk;
  335. X
  336. X     m_at = Def_macro( "@", cp->ce_fname,M_MULTI );
  337. X     m_g  = Def_macro( ">", cp->ce_lib,  M_MULTI );
  338. X     m_q  = Def_macro( "?", outall,      M_MULTI );
  339. X     m_b  = Def_macro( "<", inf,         M_MULTI );
  340. X     m_l  = Def_macro( "&", all,         M_MULTI );
  341. X     m_bb = Def_macro( "*", how->hw_per, M_MULTI );
  342. X     m_up = Def_macro( "^", imm,         M_MULTI );
  343. X
  344. X     _recipes[ RP_RECIPE ] = how->hw_recipe;
  345. X
  346. X     if( !(how->hw_flag & F_SINGLE) )
  347. X        rval = _exec_commands( cp, how );
  348. X     else {
  349. X        _drop_mac( m_q );
  350. X        SET_TOKEN( &tk, outall );
  351. X
  352. X        Doing_bang = TRUE;
  353. X        name = Get_token( &tk, "", FALSE );
  354. X        do {
  355. X           m_q->ht_value = name;
  356. X
  357. X           Wait_for_completion = TRUE;    /* Reset in _exec_commands */
  358. X           rval = _exec_commands( cp, how );
  359. X           Unlink_temp_files(how);
  360. X        }
  361. X        while( *(name = Get_token( &tk, "", FALSE )) != '\0' );
  362. X        Doing_bang = FALSE;
  363. X        Update_time_stamp( cp, how );
  364. X
  365. X        m_q->ht_value = NIL(char);
  366. X     }
  367. X
  368. X     _drop_mac( m_g  );
  369. X     _drop_mac( m_q  );
  370. X     _drop_mac( m_b  );
  371. X     _drop_mac( m_l  );
  372. X     _drop_mac( m_bb );
  373. X     _drop_mac( m_up );
  374. X      }
  375. X      else if( !(cp->ce_flag & F_RULES) &&
  376. X           ((cp != Root) || !(cp->ce_flag & F_EXPLICIT)) )
  377. X     Fatal( "Don't know how to make `%s'",cp->CE_NAME );
  378. X      else {
  379. X         /* Empty recipe, set the how flag as MADE and update the time stamp */
  380. X     Update_time_stamp( cp, how );
  381. X      }
  382. X   }
  383. X   else {
  384. X      /* Make sure everyone gets remade if Force is set */
  385. X      if( !(cp->ce_flag & F_TARGET) && Force ) cp->ce_time = Do_time();
  386. X
  387. X      /* Set how to MADE since it is done, it was not out of date */
  388. X      how->hw_flag |= F_MADE;
  389. X      if( cp->CE_HOW == how ) {
  390. X     tcp = cp;
  391. X     do {
  392. X        tcp->ce_flag |= F_MADE;
  393. X        tcp = tcp->ce_all;
  394. X     }
  395. X     while( tcp != NIL(CELL) && tcp != cp );
  396. X      }
  397. X   }
  398. X
  399. X   if( cp->CE_HOW == how ) cp->ce_flag |= F_VISITED;
  400. X
  401. Xstop_making_it:
  402. X   if( m_at != NIL(HASH) ) _drop_mac( m_at );
  403. X
  404. X   if( push )  Pop_dir(FALSE);
  405. X
  406. X   if( inf    != NIL(char) ) FREE( inf    );
  407. X   if( all    != NIL(char) ) FREE( all    );
  408. X   if( imm    != NIL(char) ) FREE( imm    );
  409. X   if( outall != NIL(char) ) FREE( outall );
  410. X
  411. X   DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
  412. X   DB_RETURN( rval );
  413. X}
  414. X
  415. X
  416. X
  417. Xstatic void
  418. X_drop_mac( hp )/*
  419. X================ set a macro value to zero. */
  420. XHASHPTR hp;
  421. X{
  422. X   if( hp->ht_value != NIL(char) ) {
  423. X      FREE( hp->ht_value );
  424. X      hp->ht_value = NIL(char);
  425. X   }
  426. X}
  427. X
  428. X
  429. X
  430. Xstatic int
  431. X_exec_commands( cp, how )/*
  432. X===========================
  433. X  Execute the commands one at a time that are pointed to by the rules pointer
  434. X  of the target cp. If a group is indicated, then the hw_attr determines
  435. X  .IGNORE and .SILENT treatment for the group.
  436. X  
  437. X  The function returns 0, if the command is executed and has successfully
  438. X  returned, and returns 1 if the command is executing but has not yet
  439. X  returned (for parallel makes).
  440. X  
  441. X  The F_MADE bit in the how cell is guaranteed set when the command has
  442. X  successfully completed.  */
  443. XCELLPTR cp;
  444. XHOWPTR  how;
  445. X{
  446. X   static HASHPTR hsh = NIL(HASH);
  447. X   register STRINGPTR    rp;
  448. X   char            *cmnd;
  449. X   char            *groupfile;
  450. X   FILE            *tmpfile;
  451. X   int            do_it;
  452. X   t_attr        attr;
  453. X   int            group;
  454. X   int            trace;
  455. X   int            rval  = 0;
  456. X
  457. X   DB_ENTER( "_exec_commands" );
  458. X
  459. X   Current_target = how;
  460. X   attr  = Glob_attr | cp->ce_attr;
  461. X   trace = Trace || !(attr & A_SILENT);
  462. X   group = how->hw_flag & F_GROUP;
  463. X
  464. X   if( group ) {
  465. X      attr  |= how->hw_attr;
  466. X      trace  = Trace || !(attr & A_SILENT);
  467. X
  468. X      if( !Trace ) tmpfile = Start_temp( Grp_suff, cp, how, &groupfile );
  469. X      if( trace )  fputs( "[\n", stdout );
  470. X
  471. X      /* Emit group prolog */
  472. X      if( attr & A_PROLOG )
  473. X         _append_file( _recipes[RP_GPPROLOG], tmpfile, cp->CE_NAME, trace );
  474. X   }
  475. X
  476. X   if( hsh == NIL(HASH) )
  477. X      hsh = Def_macro("USESHELL", NIL(char), M_MULTI|M_EXPANDED);
  478. X
  479. X   /* Process commands in recipe. If in group, merely append to file.
  480. X    * Otherwise, run them.  */
  481. X   for( rp = _recipes[RP_RECIPE]; rp != NIL(STRING); rp=rp->st_next,FREE(cmnd)){
  482. X      t_attr a_attr = attr|how->hw_attr|rp->st_attr;
  483. X      int    shell  = ((a_attr & A_SHELL) != 0);
  484. X
  485. X      Swap_on_exec  = ((a_attr & A_SWAP) != 0);      /* Swapping for DOS only */
  486. X      hsh->ht_value = (group||shell)?"yes":"no";
  487. X      do_it = !Trace;
  488. X
  489. X      if( !group && Trace && _strstr(rp->st_string,"$(MAKE)") ) {
  490. X     Wait_for_completion |= Trace;
  491. X     do_it = TRUE;
  492. X      }
  493. X
  494. X      /* Expand needs these set to properly handle some GNU style functions */
  495. X      Recipe_cell = cp;
  496. X      Recipe_how  = how;
  497. X      cmnd = Expand( rp->st_string );
  498. X
  499. X      if( group )
  500. X         Append_line( cmnd, TRUE, tmpfile, cp->CE_NAME, trace, 0 );
  501. X      else {
  502. X     if( *_strspn(cmnd, " \t") != '\0' )
  503. X        _print_cmnd(cmnd, !(do_it && ((rp->st_attr | attr) & A_SILENT)), 0);
  504. X     else
  505. X        do_it = FALSE;
  506. X
  507. X     rval=Do_cmnd(cmnd,FALSE,do_it,cp,how,((attr|rp->st_attr)&A_IGNORE)!=0,
  508. X              shell, rp->st_next == NIL(STRING) );
  509. X      }
  510. X   }
  511. X
  512. X   /* If it is a group then output the EPILOG if required and possibly
  513. X    * execute the command */
  514. X   if( group ) {
  515. X      if( attr & A_EPILOG )    /* emit epilog */
  516. X     _append_file( _recipes[RP_GPEPILOG], tmpfile, cp->CE_NAME, trace );
  517. X
  518. X      if( trace ) fputs("]\n", stdout);
  519. X
  520. X      if( do_it = !Trace ) Close_temp( how, tmpfile );
  521. X      rval = Do_cmnd(groupfile, TRUE, do_it, cp, how, (attr & A_IGNORE)!=0,
  522. X             TRUE, TRUE);
  523. X   }
  524. X
  525. X   Wait_for_completion = FALSE;
  526. X   DB_RETURN( rval );
  527. X}
  528. X
  529. X
  530. Xstatic void
  531. X_print_cmnd( cmnd, echo, map )/*
  532. X================================
  533. X   This routine is called to print out the command to stdout.  If echo is
  534. X   false the printing to stdout is supressed, but the new lines in the command
  535. X   are still deleted. */
  536. Xchar *cmnd;
  537. Xint  echo;
  538. Xint  map;
  539. X{
  540. X   register char *p;
  541. X   register char *n;
  542. X
  543. X   DB_ENTER( "_print_cmnd" );
  544. X
  545. X   if( echo ) {
  546. X      printf( "%s\n", cmnd  );
  547. X      fflush(stdout);
  548. X   }
  549. X
  550. X   for( p=cmnd; (n = strchr(p, CONTINUATION_CHAR)) != NIL(char); )
  551. X      if(n[1] == '\n') {
  552. X     DB_PRINT( "make", ("fixing [%s]", p) );
  553. X     strcpy( n, n+2 );
  554. X     p = n;
  555. X      }
  556. X      else {
  557. X     if( map ) Map_esc( n );
  558. X     p = n+1;
  559. X      }
  560. X
  561. X   DB_VOID_RETURN;
  562. X}
  563. X
  564. X
  565. X
  566. X/* These routines are used to maintain a stack of directories when making
  567. X * the targets.  If a target cd's to the directory then it is assumed that
  568. X * it will undo it when it is finished making itself. */
  569. X
  570. Xstatic STRINGPTR dir_stack = NIL(STRING);
  571. X
  572. Xint
  573. XPush_dir( cp, ignore )/*
  574. X==========================
  575. X   Change the current working directory to dir and save the current
  576. X   working directory on the stack so that we can come back.
  577. X   
  578. X   If ignore is TRUE then do not complain about _ch_dir if not possible.*/
  579. XCELLPTR cp;
  580. Xint  ignore;
  581. X{
  582. X   STRINGPTR   new_dir;
  583. X   char        *dir;
  584. X
  585. X   DB_ENTER( "Push_dir" );
  586. X
  587. X   if( (dir = cp->ce_dir) == NIL(char) ) dir = Pwd;
  588. X   if( *dir == '\'' && dir[strlen(dir)-1] == '\'' ) {
  589. X      dir = _strdup(dir+1);
  590. X      dir[strlen(dir)-1]='\0';
  591. X   }
  592. X   else
  593. X      dir = Expand(dir);
  594. X
  595. X   if( Set_dir(dir) ) {
  596. X      if( !ignore )
  597. X         Fatal( "Unable to change to directory `%s', target is [%s]",
  598. X            dir, cp->CE_NAME );
  599. X      FREE(dir);
  600. X      DB_RETURN( 0 );
  601. X   }
  602. X
  603. X   DB_PRINT( "dir", ("Push: [%s]", dir) );
  604. X   if( Verbose ) printf( "%s:  Changed to directory [%s]\n", Pname, dir  );
  605. X
  606. X   FREE( dir );
  607. X   TALLOC( new_dir, 1, STRING );
  608. X   new_dir->st_next   = dir_stack;
  609. X   dir_stack          = new_dir;
  610. X   new_dir->st_string = _strdup( Pwd );
  611. X
  612. X   Def_macro( "PWD", Get_current_dir(), M_MULTI | M_EXPANDED );
  613. X   _set_tmd();
  614. X
  615. X   DB_RETURN( 1 );
  616. X}
  617. X
  618. X
  619. X
  620. Xvoid
  621. XPop_dir(ignore)/*
  622. X=================
  623. X   Change the current working directory to the previous saved dir. */
  624. Xint ignore;
  625. X{
  626. X   STRINGPTR old_dir;
  627. X   char      *dir;
  628. X
  629. X   DB_ENTER( "Pop_dir" );
  630. X
  631. X   if( dir_stack == NIL(STRING) )
  632. X      if( ignore ) {
  633. X         DB_VOID_RETURN;
  634. X      }
  635. X      else
  636. X     Error( "Directory stack empty for return from .SETDIR" );
  637. X
  638. X   if( Set_dir(dir = dir_stack->st_string) )
  639. X      Fatal( "Could not change to directory `%s'", dir );
  640. X
  641. X   Def_macro( "PWD", dir, M_MULTI | M_EXPANDED );
  642. X   DB_PRINT( "dir", ("Pop: [%s]", dir) );
  643. X   if( Verbose ) printf( "%s:  Changed back to directory [%s]\n", Pname, dir);
  644. X
  645. X   old_dir   = dir_stack;
  646. X   dir_stack = dir_stack->st_next;
  647. X
  648. X   FREE( old_dir->st_string );
  649. X   FREE( old_dir );
  650. X   _set_tmd();
  651. X
  652. X   DB_VOID_RETURN;
  653. X}
  654. X
  655. X
  656. X
  657. Xstatic void
  658. X_set_tmd()/*
  659. X============
  660. X   Set the TWD Macro */
  661. X{
  662. X   TKSTR md, pd;
  663. X   char  *m, *p;
  664. X   char  *tmd;
  665. X   int   is_sep;
  666. X   int   first = 1;
  667. X
  668. X   SET_TOKEN( &md, Makedir );
  669. X   SET_TOKEN( &pd, Pwd );
  670. X
  671. X   m = Get_token( &md, DirBrkStr, FALSE );
  672. X   (void) Get_token( &pd, DirBrkStr, FALSE );
  673. X   is_sep = (strchr(DirBrkStr, *m) != NIL(char));
  674. X   tmd = _strdup( "" );
  675. X
  676. X   do {
  677. X      m = Get_token( &md, DirBrkStr, FALSE );
  678. X      p = Get_token( &pd, DirBrkStr, FALSE );
  679. X
  680. X      if( !is_sep && strcmp(m, p) ) {    /* they differ */
  681. X     char *tmp;
  682. X     if( first ) {        /* They differ in the first component    */
  683. X        tmd = Makedir;    /* In this case use the full path    */
  684. X        break;
  685. X     }
  686. X
  687. X     if( *p ) tmp = Build_path( "..", tmd );
  688. X     if( *m ) tmp = Build_path( tmd, m );
  689. X     FREE( tmd );
  690. X     tmd = _strdup( tmp );
  691. X      }
  692. X
  693. X      is_sep = 1-is_sep;
  694. X      first  = 0;
  695. X   } while (*m || *p);
  696. X
  697. X   CLEAR_TOKEN( &md );
  698. X   CLEAR_TOKEN( &pd );
  699. X
  700. X   Def_macro( "TMD", tmd, M_MULTI | M_EXPANDED );
  701. X   if( tmd != Makedir ) FREE( tmd );
  702. X}
  703. X
  704. X
  705. Xstatic void
  706. X_set_recipe( target, ind )/*
  707. X============================
  708. X   Set up the _recipes static variable so that the slot passed in points
  709. X   at the rules corresponding to the target supplied. */
  710. Xchar *target;
  711. Xint  ind;
  712. X{
  713. X   CELLPTR cp;
  714. X   HASHPTR hp;
  715. X
  716. X   if( (hp = Get_name( target, Defs, FALSE, NIL(CELL) )) != NIL(HASH) ) {
  717. X      cp = hp->CP_OWNR;
  718. X      if( cp->CE_HOW != NIL(HOW) ) _recipes[ ind ] = cp->CE_RECIPE;
  719. X   }
  720. X   else
  721. X      _recipes[ ind ] = NIL(STRING);
  722. X}
  723. X
  724. X
  725. X
  726. Xvoid
  727. XAppend_line( cmnd, newline, tmpfile, name, printit, map )
  728. Xchar *cmnd;
  729. Xint  newline;
  730. XFILE *tmpfile;
  731. Xchar *name;
  732. Xint  printit;
  733. Xint  map;
  734. X{
  735. X   _print_cmnd( cmnd, printit, map );
  736. X
  737. X   if( Trace ) return;
  738. X
  739. X   fputs(cmnd, tmpfile);
  740. X   if( newline ) fputc('\n', tmpfile);
  741. X   fflush(tmpfile);
  742. X
  743. X   if( ferror(tmpfile) )
  744. X      Fatal("Write error on temporary file, while processing `%s'", name);
  745. X}
  746. X
  747. X
  748. X
  749. Xstatic void
  750. X_append_file( rp, tmpfile, name, printit )
  751. Xregister STRINGPTR rp;
  752. XFILE            *tmpfile;
  753. Xchar            *name;
  754. Xint            printit;
  755. X{
  756. X   char *cmnd;
  757. X
  758. X   while( rp != NIL(STRING) ) {
  759. X      Append_line(cmnd = Expand(rp->st_string), TRUE, tmpfile, name, printit,0);
  760. X      FREE(cmnd);
  761. X      rp = rp->st_next;
  762. X   }
  763. X}
  764. SHAR_EOF
  765. echo "File make.c is complete"
  766. chmod 0440 make.c || echo "restore of make.c fails"
  767. echo "x - extracting make.bat (Text)"
  768. sed 's/^X//' << 'SHAR_EOF' > make.bat &&
  769. Xecho off
  770. Xrem  *** This is the make batchfile that is used under MSDOS to make the
  771. Xrem  *** first version of dmake.  It isn't pretty but it does work, assuming
  772. Xrem  *** the compilers have been correctly setup.  See the warning below
  773. Xrem  *** concerning tlink, if you are making the Turbo C version.
  774. Xrem
  775. Xecho Running make.bat script to make a %1 copy of dmake.
  776. X
  777. Xif %0%1 == %0 goto error
  778. Xif %1 == msc goto makemsc
  779. Xif %1 == msc60 goto makemsc60
  780. Xif %1 == mscswp goto makemscswp
  781. Xif %1 == msc60swp goto makemsc60swp
  782. Xif %1 == tcc goto maketcc
  783. Xif %1 == tccswp goto maketccswp
  784. X
  785. Xrem label the possible DOS variations for dmake here.
  786. X:error
  787. Xecho INDEX:  You must specify one of:
  788. Xecho    tcc      - Turbo C 2.0, compile.
  789. Xecho    tccswp   - Turbo C 2.0 compile of swapping dmake.
  790. Xecho    msc      - Microsoft C 4.0 to 5.1, compile.
  791. Xecho    msc60    - Microsoft C 6.0 compile.
  792. Xecho    mscswp   - Microsoft C 4.0 to 5.1, MASM 5.1 compile of swapping dmake.
  793. Xecho    msc60swp - Microsoft C 6.0, MASM 5.1 compile of swapping dmake.
  794. Xgoto end
  795. X
  796. Xrem This is the script that makes dmake using Microsoft C 4.0 or higher.
  797. X:makemsc
  798. Xmsdos\mscdos\mk.bat
  799. Xgoto end
  800. X
  801. Xrem This is the script that makes dmake using Microsoft C 4.0 or higher.
  802. X:makemsc60
  803. Xmsdos\mscdos\mk60.bat
  804. Xgoto end
  805. X
  806. X:makemscswp
  807. Xmsdos\mscdos\mkswp.bat
  808. Xgoto end
  809. X
  810. X:makemscswp
  811. Xmsdos\mscdos\mk60swp.bat
  812. Xgoto end
  813. X
  814. Xrem This is the script that makes dmake using Turbo C 2.0 or higher.
  815. Xrem This is the script that makes dmake using Turbo C 2.0 or higher.
  816. X:maketcc
  817. Xcls
  818. Xecho WARNING:
  819. Xecho    The default response files:
  820. Xecho        msdos\tccdos\obj.rsp
  821. Xecho        msdos\tccdos\lib.rsp
  822. Xecho    contain absolute paths to TURBO-C runtime startup objects, and to
  823. Xecho    the standard libraries.  You should check that these files contain
  824. Xecho    the correct path names for your installation of Turbo-C before
  825. Xecho    proceeding further.
  826. Xecho --
  827. Xecho Continue if ok, or abort and edit the response files.
  828. Xpause
  829. Xmsdos\tccdos\mk.bat
  830. Xgoto end
  831. X
  832. X:maketccswp
  833. Xcls
  834. Xecho WARNING:
  835. Xecho    The default response files:
  836. Xecho        msdos\tccdos\objswp.rsp
  837. Xecho        msdos\tccdos\libswp.rsp
  838. Xecho    contain absolute paths to TURBO-C runtime startup objects, and to
  839. Xecho    the standard libraries.  You should check that these files contain
  840. Xecho    the correct path names for your installation of Turbo-C before
  841. Xecho    proceeding further.
  842. Xecho --
  843. Xecho Continue if ok, or abort and edit the response files.
  844. Xpause
  845. Xmsdos\tccdos\mkswp.bat
  846. X
  847. Xrem All done!
  848. X:end
  849. SHAR_EOF
  850. chmod 0440 make.bat || echo "restore of make.bat fails"
  851. echo "x - extracting macparse.c (Text)"
  852. sed 's/^X//' << 'SHAR_EOF' > macparse.c &&
  853. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/macparse.c,v 1.1 90/10/06 12:03:57 dvadura Exp $
  854. X-- SYNOPSIS -- parse a macro definition
  855. X-- 
  856. X-- DESCRIPTION
  857. X--    This file contains the code that parses a macro definition
  858. X--    stored in a buffer.  If the string in buffer is not a valid
  859. X--    macro definition the routie Parse_macro returns 0, otherwise it
  860. X--    returns 1 to indicate success.
  861. X-- 
  862. X-- AUTHOR
  863. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  864. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  865. X--
  866. X-- COPYRIGHT
  867. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  868. X-- 
  869. X--      This program is free software; you can redistribute it and/or
  870. X--      modify it under the terms of the GNU General Public License
  871. X--      (version 1), as published by the Free Software Foundation, and
  872. X--      found in the file 'LICENSE' included with this distribution.
  873. X-- 
  874. X--      This program is distributed in the hope that it will be useful,
  875. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  876. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  877. X--      GNU General Public License for more details.
  878. X-- 
  879. X--      You should have received a copy of the GNU General Public License
  880. X--      along with this program;  if not, write to the Free Software
  881. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  882. X--
  883. X-- LOG
  884. X--     $Log:    macparse.c,v $
  885. X * Revision 1.1  90/10/06  12:03:57  dvadura
  886. X * dmake Release, Version 3.6
  887. X * 
  888. X*/
  889. X
  890. X#include <ctype.h>
  891. X#include "extern.h"
  892. X#include "alloc.h"
  893. X#include "db.h"
  894. X
  895. Xint
  896. XParse_macro( buffer, flag )/*
  897. X=============================
  898. X   Parse the string in buffer and define it as a macro if it is a valid macro.
  899. X   Note especially the string .SETDIR= since it is an attribute, but looks a
  900. X   lot like a macro definition.  This would not be a problem if make used
  901. X   white space as token separators, since this is not the case we must do
  902. X   something about it. */
  903. Xchar *buffer;
  904. Xint  flag;
  905. X{
  906. X   register char *tok1;        /* temporary place to keep a token */
  907. X   register char *tok2;        /* temporary place to keep a token */
  908. X   char         *result;    /* temporary pointer for strings   */
  909. X   TKSTR          input;        /* place to scan the buffer from   */
  910. X   HASHPTR      hv;        /* pointer to hash table value       */
  911. X   int          operator;    /* what macro operator do we have  */
  912. X
  913. X   DB_ENTER( "Parse_macro" );
  914. X
  915. X   SET_TOKEN( &input, buffer );
  916. X   tok1 = Get_token( &input, "=+:*", -1 );
  917. X
  918. X   if( Macro_op( tok1 ) ) {
  919. X      Error( "No macro name" );
  920. X      CLEAR_TOKEN( &input );
  921. X      DB_RETURN( 1 );
  922. X   }
  923. X
  924. X   tok1 = _strdup( tok1 );
  925. X   tok2 = Get_token( &input, "=+:*", -1 );
  926. X   if( !(operator = Macro_op( tok2 )) || !strcmp( tok1, ".SETDIR") )
  927. X   {
  928. X      CLEAR_TOKEN( &input );
  929. X      FREE( tok1 );
  930. X      DB_RETURN( 0 );
  931. X   }
  932. X
  933. X   tok2 = Expand(tok1); FREE(tok1); tok1 = tok2;
  934. X   tok2 = Get_token( &input, NIL( char ), FALSE );
  935. X
  936. X   switch( operator ) {
  937. X      case M_OP_PLCL:
  938. X      tok2 = Expand( tok2 );
  939. X      /* Fall thru */
  940. X
  941. X      case M_OP_PL:
  942. X     /* Add to an existing macro, if it is not defined, though, then
  943. X      * just define a new macro */
  944. X
  945. X     if( (hv = GET_MACRO(tok1)) == NIL(HASH) || hv->ht_value == NIL(char) )
  946. X        Def_macro( tok1, tok2, flag );
  947. X     else {
  948. X        result = _stradd( hv->ht_value, tok2, FALSE );
  949. X        Def_macro( tok1, result, flag );
  950. X        FREE( result );
  951. X     }
  952. X     if( operator == M_OP_PLCL ) FREE(tok2);
  953. X     break;
  954. X
  955. X      case M_OP_DF:
  956. X      if( (hv = GET_MACRO(tok1)) != NIL(HASH) )
  957. X        break;
  958. X     /* else FALLTHRU */
  959. X
  960. X      case M_OP_EQ:
  961. X     Def_macro( tok1, tok2, flag );
  962. X     break;
  963. X
  964. X      case M_OP_DFCL:
  965. X      if( (hv = GET_MACRO(tok1)) != NIL(HASH) )
  966. X        break;
  967. X     /* else FALLTHRU */
  968. X
  969. X      case M_OP_CL:
  970. X     /* If the macro we are assigning from is a single control
  971. X      * macro with nothing else, then we propagate the M_MULTI
  972. X      * flag to the macro we are assigning the value to so that
  973. X      * the same macro can be used to do this over and over. */
  974. X     If_multi = 0;
  975. X     tok2 = Expand( tok2 );
  976. X     Def_macro( tok1, tok2, M_EXPANDED | flag | If_multi );
  977. X     FREE( tok2 );
  978. X     break;
  979. X   }
  980. X        
  981. X   FREE( tok1 );
  982. X
  983. X   DB_RETURN( 1 );
  984. X}
  985. X
  986. X
  987. X
  988. Xint
  989. XMacro_op( op )/*
  990. X================
  991. X   Check the passed in op string and map it to one of the macro operators */
  992. Xchar *op;
  993. X{
  994. X   int ret = 0;
  995. X
  996. X   DB_ENTER( "macro_op" );
  997. X
  998. X   switch( *op ) {
  999. X      case '=': ret = M_OP_EQ; break;
  1000. X      case ':': ret = M_OP_CL; op++; break;
  1001. X
  1002. X      case '+':
  1003. X         ret = M_OP_PL; op++;
  1004. X         if( *op == ':' ) { ret = M_OP_PLCL; op++; }
  1005. X         break;
  1006. X
  1007. X      case '*':
  1008. X         ret = M_OP_DF; op++;
  1009. X         if( *op == ':' ) { ret = M_OP_DFCL; op++; }
  1010. X         break;
  1011. X   }
  1012. X
  1013. X   if( *op++ != '=' )
  1014. X      ret = 0;
  1015. X   else if( *op != '\0' )
  1016. X      ret = 0;
  1017. X
  1018. X   DB_RETURN( ret );
  1019. X}
  1020. X
  1021. SHAR_EOF
  1022. chmod 0440 macparse.c || echo "restore of macparse.c fails"
  1023. echo "x - extracting infer.c (Text)"
  1024. sed 's/^X//' << 'SHAR_EOF' > infer.c &&
  1025. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/infer.c,v 1.1 90/10/06 12:03:54 dvadura Exp $
  1026. X-- SYNOPSIS -- infer how to make a target.
  1027. X-- 
  1028. X-- DESCRIPTION
  1029. X--    This file contains the code to infer a recipe, and possibly some new
  1030. X--    prerequisites for a target which dmake does not know how to make, or
  1031. X--    has no explicit recipe.
  1032. X--
  1033. X--    The inference fails if no path through the inference graph can be
  1034. X--    found by which we can make the target.
  1035. X-- 
  1036. X-- AUTHOR
  1037. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  1038. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  1039. X--
  1040. X-- COPYRIGHT
  1041. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  1042. X-- 
  1043. X--      This program is free software; you can redistribute it and/or
  1044. X--      modify it under the terms of the GNU General Public License
  1045. X--      (version 1), as published by the Free Software Foundation, and
  1046. X--      found in the file 'LICENSE' included with this distribution.
  1047. X-- 
  1048. X--      This program is distributed in the hope that it will be useful,
  1049. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  1050. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1051. X--      GNU General Public License for more details.
  1052. X-- 
  1053. X--      You should have received a copy of the GNU General Public License
  1054. X--      along with this program;  if not, write to the Free Software
  1055. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1056. X--
  1057. X-- LOG
  1058. X--     $Log:    infer.c,v $
  1059. X * Revision 1.1  90/10/06  12:03:54  dvadura
  1060. X * dmake Release, Version 3.6
  1061. X * 
  1062. X*/
  1063. X
  1064. X#include "extern.h"
  1065. X#include "alloc.h"
  1066. X#include "db.h"
  1067. X
  1068. X/* attributes that get transfered from the % start cell to the inferred
  1069. X * cells. */
  1070. X
  1071. X#define A_TRANSFER  (A_EPILOG | A_PRECIOUS | A_SILENT | A_SHELL |\
  1072. X             A_SEQ | A_LIBRARY | A_IGNORE | A_PROLOG | A_SWAP)
  1073. X
  1074. X/* Define local static functions */
  1075. Xstatic DFALINKPTR _dfa_subset  ANSI((DFALINKPTR, DFASETPTR));
  1076. Xstatic void       _free_dfas   ANSI((DFALINKPTR));
  1077. Xstatic int      _count_dots  ANSI((char *));
  1078. Xstatic char *      _build_name  ANSI((char *, char *, char *));
  1079. X
  1080. Xstatic int _prep = -1;    /* Integer value of Prep variable */
  1081. Xstatic int _dmax;
  1082. X
  1083. XCELLPTR
  1084. XInfer_recipe( cp, how, dfa_stack, setdirroot )/*
  1085. X================================================
  1086. X    Infer a set of rules for making a target.  We know we have a HOW
  1087. X    cell attached, but it's prerequisite list may be NIL as is its
  1088. X    recipe!  A NIL recipe is a prerequisite for calling this routine. */
  1089. XCELLPTR    cp;
  1090. XHOWPTR     how;
  1091. XDFASETPTR  dfa_stack;
  1092. XCELLPTR    setdirroot;
  1093. X{
  1094. X   DFALINKPTR    pdfa;
  1095. X   DFALINKPTR    dfas;
  1096. X   CELLPTR    infcell;
  1097. X   CELLPTR    meta;
  1098. X   DFASET    top_dfa_stack;
  1099. X   EDGEPTR      pedge;
  1100. X
  1101. X   DB_ENTER( "Infer_recipe" );
  1102. X   DB_PRINT( "inf", (">>> Infer for target [%s]", cp->CE_NAME) );
  1103. X   DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long)coreleft()));
  1104. X
  1105. X   /* If no further transitive closure on this cell then don't perform
  1106. X    * any more inferences */
  1107. X   if( cp->ce_attr & A_NOINFER ) DB_RETURN(NIL(CELL));
  1108. X   if( _prep == -1 ) _prep = atoi(Prep);  /* _dfa_subset needs _prep */
  1109. X
  1110. X   if( dfa_stack == NIL(DFASET) )
  1111. X      _dmax = _prep + _count_dots(cp->CE_NAME);
  1112. X
  1113. X   /* If none of the inference nodes match then forget about the inference.
  1114. X    * The user did not tell us how to make such a target.  We also stop the
  1115. X    * Inference if the new set of DFA's is a proper subset of a previous
  1116. X    * subset and it's PREP counts exceed the value of Prep.
  1117. X    */
  1118. X   dfas = _dfa_subset( Match_dfa(cp->CE_NAME), dfa_stack );
  1119. X
  1120. X#ifdef DBUG
  1121. X   { char      *tmp;
  1122. X     DFASETPTR ds;
  1123. X
  1124. X      tmp = _strdup("");
  1125. X      for( pdfa = dfas; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
  1126. X         tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME );
  1127. X
  1128. X      DB_PRINT( "inf", ("Working DFA subset [%s]", tmp) );
  1129. X      FREE( tmp );
  1130. X
  1131. X      tmp = _strdup( "{" );
  1132. X      for( ds = dfa_stack; ds != NIL(DFASET); ds = ds->df_next ) {
  1133. X     tmp = _strapp( tmp, "[" );
  1134. X     for( pdfa = ds->df_set; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
  1135. X        tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME );
  1136. X     tmp = _strapp( tmp, "]" );
  1137. X      }
  1138. X      tmp = _strapp( tmp, "}" );
  1139. X
  1140. X      DB_PRINT( "inf", ("DFA stack:  %s", tmp) );
  1141. X      FREE(tmp);
  1142. X   }
  1143. X#endif
  1144. X
  1145. X   if( dfas == NIL(DFALINK) ) {
  1146. X      DB_PRINT( "mem", ("%s:<- mem %ld",cp->CE_NAME, (long)coreleft()));
  1147. X      DB_PRINT( "inf", ("<<< Exit, no dfas, cp = %04x", NIL(CELL)) );
  1148. X      DB_RETURN( NIL(CELL) );
  1149. X   }
  1150. X
  1151. X
  1152. X   /* We have a set of %-meta's that have not previously been considered, or
  1153. X    * whose counts do not violate the Prep count.  So we should consider
  1154. X    * them, and put them on the top of the stack.
  1155. X    */
  1156. X   top_dfa_stack.df_set  = dfas;
  1157. X   top_dfa_stack.df_next = dfa_stack;
  1158. X
  1159. X
  1160. X   /* Run through the %-meta cells, build the prerequisite cells.  If we are
  1161. X    * performing transitive closure, then call Infer_recipe with the new
  1162. X    * prerequisite.
  1163. X    */
  1164. X   for( pdfa = dfas, infcell = NIL(CELL), pedge = NIL(EDGE);
  1165. X        pdfa != NIL(DFALINK);
  1166. X        pdfa = pdfa->dl_next ) {
  1167. X      int     push   = 0;
  1168. X      int     _trans = 0;
  1169. X      EDGEPTR edge;
  1170. X      EDGEPTR edge_noprq;    /* No prerequisite for this edge */
  1171. X
  1172. X      DB_PRINT( "inf", ("Using dfa:  [%s]", pdfa->dl_meta->CE_NAME) );
  1173. X      meta = pdfa->dl_meta;
  1174. X
  1175. X
  1176. X      /* Change to the required directory prior to checking the prerequisites
  1177. X       * Only if the meta has a directory and we haven't changed dir's
  1178. X       * for the CELL already.
  1179. X       *
  1180. X       * Ignore the %-meta if we had to change to a dir, and the dir
  1181. X       * did not exist.
  1182. X       */
  1183. X      if( !(cp->ce_attr & A_SETDIR) && meta->ce_dir != NIL(char) )
  1184. X     if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != meta->ce_dir) &&
  1185. X         (push = Push_dir(meta, TRUE)) )
  1186. X        setdirroot = cp;
  1187. X     else {
  1188. X        DB_PRINT( "inf", ("Failed PUSH of [%s]", meta->ce_dir) );
  1189. X        continue;
  1190. X     }
  1191. X
  1192. X
  1193. X      /* Now run through the list of prerequisite edge's for the %-meta.
  1194. X       * Build each prerequisite in turn, and then see if it needs to be
  1195. X       * inferred.  We treat the edge that has NO prerequisites last, as
  1196. X       * it gives a recipe for making a %-meta from no prerequisites, and
  1197. X       * we should really check all NON-NULL prerequisites first.
  1198. X       */
  1199. X      edge = meta->CE_EDGES;
  1200. X      edge_noprq = NIL(EDGE);
  1201. X
  1202. X      do {
  1203. X         pedge = edge;
  1204. X
  1205. X     if( edge->ed_prq == NIL(CELL) )
  1206. X        edge_noprq = edge;
  1207. X     else {
  1208. X        HASHPTR  thp;    /* temporary hash table pointer        */
  1209. X        HASH     iprqh;    /* hash cell for new prerequisite    */
  1210. X        CELL     iprq;    /* inferred prerequisite to look for    */
  1211. X        CELLPTR  sdir;    /* local setdir root for inference    */
  1212. X        STRINGPTR sp   = NIL(STRING); /* pointer to rcp of inferred target*/
  1213. X        int      ipush = 0;          /* flag for push on inferred prereq */
  1214. X        char     *name = edge->ed_prq->CE_NAME;
  1215. X        int          _dmax_fix;
  1216. X
  1217. X        DB_PRINT( "inf", ("Trying edge from [%s] to [%s] for [%s]",
  1218. X                  meta->CE_NAME, name, cp->CE_NAME) );
  1219. X
  1220. X        _trans = Transitive &&
  1221. X             !((Glob_attr | edge->ed_prq->ce_attr) & A_NOINFER);
  1222. X
  1223. X        /* Set the temp CELL used for building prerequisite candidates to
  1224. X         * all zero so that we don't have to keep initializing all the
  1225. X         * fields. */
  1226. X        {
  1227. X           register char *s = (char *) &iprq;
  1228. X           register int   n = sizeof(CELL);
  1229. X           while( n ) { *s++ = '\0'; n--; }
  1230. X        }
  1231. X
  1232. X
  1233. X        /* Build the prerequisite name from the %-meta prerequisite given
  1234. X         * for the %-meta rule. */
  1235. X        iprqh.ht_name = _build_name( cp->CE_NAME, name, pdfa->dl_per );
  1236. X        if( strcmp(cp->CE_NAME, iprqh.ht_name) == 0 )
  1237. X           goto try_next_edge;
  1238. X        if((_dmax_fix = (_count_dots(name)-_count_dots(meta->CE_NAME))) < 0)
  1239. X           _dmax_fix = 0;
  1240. X        if( _count_dots(iprqh.ht_name) > _dmax + _dmax_fix )
  1241. X           goto try_next_edge;
  1242. X
  1243. X        DB_PRINT( "inf", ("Checking prerequisite [%s]", iprqh.ht_name) );
  1244. X
  1245. X        if( Verbose )
  1246. X           printf( "%s:  Trying prerequisite [%s] for [%s]\n", Pname,
  1247. X               iprqh.ht_name, cp->CE_NAME );
  1248. X
  1249. X
  1250. X        /* See if the prerequisite CELL has been previously defined.  If
  1251. X         * it has, then make a copy of it into iprq, and use it to try
  1252. X         * the inference.  We make the copy so that we don't modify the
  1253. X         * stat of the inferred cell if the inference fails.
  1254. X         */
  1255. X        thp = Get_name( iprqh.ht_name, Defs, FALSE, setdirroot );
  1256. X        if(thp != NIL(HASH)) {
  1257. X           iprq = *thp->CP_OWNR;
  1258. X           if( iprq.CE_HOW != NIL(HOW) ) sp = iprq.CE_HOW->hw_recipe;
  1259. X        }
  1260. X        else
  1261. X           iprq.ce_name  = &iprqh;
  1262. X
  1263. X
  1264. X        /* If the prerequisite has the .SETDIR attr set, then we
  1265. X         * should try to CD to the directory, if it is really different
  1266. X         * from the one we are currently in.  If the CD fails we ignore
  1267. X         * the edge and go try another edge.
  1268. X         */
  1269. X        sdir = setdirroot;
  1270. X        if( iprq.ce_dir != NIL(char) )
  1271. X           if( sdir==NIL(CELL) || sdir->ce_dir != iprq.ce_dir )
  1272. X              if( ipush = Push_dir(&iprq, TRUE) )
  1273. X             sdir = &iprq;
  1274. X          else
  1275. X             goto try_next_edge;
  1276. X
  1277. X
  1278. X        /* Stat the inferred prerequisite.
  1279. X         */
  1280. X        if( !(iprq.ce_flag & F_STAT) ) Stat_target( &iprq, FALSE );
  1281. X
  1282. X
  1283. X        /* If the STAT succeeded or if the prerequisite has a recipe for
  1284. X         * making it, then infer it.  We may later try to perform a
  1285. X         * second inference on this prerequisite when we actually go to
  1286. X         * make it.
  1287. X         */
  1288. X        if( (iprq.ce_time != (time_t)0L) || (sp != NIL(STRING)) ) {
  1289. X           infcell = Def_cell( iprqh.ht_name, setdirroot );
  1290. X           infcell->ce_flag |= F_REMOVE;
  1291. X        }
  1292. X        else
  1293. X           /* The STAT did not succeed, so call Infer_recipe recursively
  1294. X            * to see if we know how to make the prerequisite.  If it
  1295. X        * returns not NULL, then we have an inferred prerequisite
  1296. SHAR_EOF
  1297. echo "End of part 19"
  1298. echo "File infer.c is continued in part 20"
  1299. echo "20" > s2_seq_.tmp
  1300. exit 0
  1301.  
  1302.